import datetime
import random


def random_num(maxValue):
    return random.randint(0, maxValue)


def operator():
    x = random.randint(0, 1)
    if x == 0:
        return "+"
    else:
        return "-"


def get_test_num(maxValue):
    a = random_num(maxValue)
    b = random_num(maxValue)
    oper = operator()

    if oper == "+":
        c = a + b
    else:
        c = a - b

    return (a, b, oper, c)


def main(maxValue=None, test_num=None):
    if not maxValue:
        maxValue = int(raw_input(u"Please input max value:"))

    if not test_num:
        test_num = int(raw_input(u"How many test:"))

    ready = raw_input(u"Press enter when ready!")

    start_time = datetime.datetime.now()

    i = 0

    wrongs = []
    time_consume = {}

    all_test = {}

    last_item = ""
    while i < test_num:

        (a, b, oper, c) = get_test_num(maxValue)
        while (a == b and a == 0) or (c > maxValue or c < 0):
            (a, b, oper, c) = get_test_num(maxValue)

        which = random_num(2)
        if which == 0:
            msg = u"( ) %s %s = %s" % (oper, b, c)
        elif which == 1:
            msg = u"%s %s ( ) = %s" % (a, oper, c)
        elif which == 2:
            msg = u"%s %s %s = ( )" % (a, oper, b)
        else:
            print("----ERROR----")

        if last_item and last_item == msg:
            continue

        last_item = msg

        one_start_time = datetime.datetime.now()

        input_num = raw_input(msg + " ? ")

        while True:
            if input_num and input_num.isdigit():
                result = int(input_num)
                break
            else:
                input_num = raw_input(msg + " ? ")

        one_end_time = datetime.datetime.now()
        one_delta = one_end_time - one_start_time
        delta_float = float(one_delta.microseconds) / 1000000.0 + float(one_delta.seconds)
        time_consume[i] = delta_float

        all_test[i] = (a, oper, b, result, c, which, msg, delta_float)

        if which == 0 and result != a:
            wrongs.append((a, oper, b, result, c, which, msg, delta_float))
        elif which == 1 and result != b:
            wrongs.append((a, oper, b, result, c, which, msg, delta_float))
        elif which == 2 and result != c:
            wrongs.append((a, oper, b, result, c, which, msg, delta_float))

        i = i + 1

    end_time = datetime.datetime.now()

    print(u"Result: ")
    print("---------------------")
    print(u"Total: %s" % test_num)
    wrong_num = len(wrongs)
    corrects = test_num - wrong_num
    print(u"Correct: %s" % corrects)
    print(u"Wrong: %s" % wrong_num)
    print(u"Correct Rate: %s%%" % (float(corrects) * 100 / float(test_num)))
    print(u"Wrong Rate: %s%%" % (float(wrong_num) * 100 / float(test_num)))

    if wrong_num > 0:
        print(u"Wrong Detail: ")

        for (a, oper, b, result, c, which, msg, delta_float) in wrongs:
            if which == 0:
                print(u"%s Input: %s, Should be: %s" % (msg, result, a))
            elif which == 1:
                print(u"%s Input: %s, Should be: %s" % (msg, result, b))
            else:
                print(u"%s Input: %s, Should be: %s" % (msg, result, c))

    delta = end_time - start_time
    print(u"Total Time: %s" % delta.seconds)

    top_num = 3
    if test_num < top_num:
        top_num = test_num

    top_time_consume = sorted(time_consume.items(), key=lambda e: e[1], reverse=True)
    print(u"Top 3 slow: ")

    i = 0
    for key in top_time_consume:
        (a, oper, b, result, c, which, msg, delta_float) = all_test.get(key[0])
        print(u" %s Time: %s" % (msg, delta_float))
        i += 1
        if i >= top_num:
            break

    low_time_consume = sorted(time_consume.items(), key=lambda e: e[1], reverse=False)
    print(u"Top 3 fast: ")

    i = 0
    for key in low_time_consume:
        (a, oper, b, result, c, which, msg, delta_float) = all_test.get(key[0])
        print(u" %s Time: %s" % (msg, delta_float))
        i += 1
        if i >= top_num:
            break

    show_all = raw_input(u"If check all test time detail(y/n):")
    if show_all == "y" or show_all == "Y":
        for key in top_time_consume:
            (a, oper, b, result, c, which, msg, delta_float) = all_test.get(key[0])
            print(u" %s time: %s" % (msg, delta_float))

    print("------------------")
    do_same = raw_input(u"Do the test again? (y/n):")
    if do_same == "" or do_same == "y":
        main(maxValue, test_num)

    next_test = raw_input(u"Are you continue? (y/n):")
    if next_test == "" or next_test == "y" or next_test == "Y" or next_test == "yes":
        main()
    else:
        import sys
        sys.exit(0)


if __name__ == "__main__":
    print "-----------------------"
    print "       Test v0.1       "
    print "-----------------------"
    main()
